package org.legzo.castorranker;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.legzo.castorranker.ranker.Game;
import org.legzo.castorranker.ranker.Player;

public class CsvRankerService implements RankerService {

	private String dataFile;
	private boolean backup = true;

	public void setDataFile(String dataFile) {
		this.dataFile = dataFile;
	}

	public void setBackup(boolean backup) {
		this.backup = backup;
	}

	public List<Game> getGames() {
		DataLoader dataLoader = new DataLoader(dataFile);
		dataLoader.loadData();
		return dataLoader.getGames();
	}

	public List<Player> getPlayers() {
		DataLoader dataLoader = new DataLoader(dataFile);
		dataLoader.loadData();
		return dataLoader.getLoadedPlayers();
	}

	public void saveGame(Game game) {
		if (game.getScores().size() == 0) {
			return;
		}

		game.rankPlayers();

		SimpleDateFormat completeFormat = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss");

		List<Game> games = getGames();
		List<Player> players = getPlayers();

		if (backup) {
			// on fait un backup du csv.
			String backFileName = dataFile + "." + System.currentTimeMillis();
			try {
				FileUtils.copyFile(new File(dataFile), new File(backFileName));
			} catch (IOException e) {
				throw new RuntimeException("Unable to backup dataFile from " + dataFile + " to " + backFileName, e);
			}
		}

		games.add(game);
		// ajout des nouveaux joueurs :
		for (Player p : game.getScores().keySet()) {
			if (!players.contains(p)) {
				players.add(p);
			}
		}

		// on positionne correctement le jeu (trié par date)
		Collections.sort(games);

		FileWriter fileWriter = null;
		try {
			fileWriter = new FileWriter(dataFile);

			// header
			String[] d = new String[1 + players.size()];
			d[0] = "date";
			int i = 1;
			for (Player p : players) {
				d[i++] = p.getName();
			}
			writeCsvLine(d, ";", fileWriter);

			// data
			for (Game g : games) {
				d[0] = completeFormat.format(g.getDate());
				i = 1;
				for (Player p : players) {
					if (g.getScores().containsKey(p)) {
						d[i++] = Integer.toString(g.getScores().get(p));
					} else {
						d[i++] = "0";
					}
				}
				writeCsvLine(d, ";", fileWriter);
			}
		} catch (IOException e) {
			throw new RuntimeException("Unable to write dataFile to " + dataFile
					+ " file is certainly corrupted. I hope you activated backups.", e);
		} finally {
			IOUtils.closeQuietly(fileWriter);
		}
	}

	public void writeCsvLine(String[] datas, String sepChar, FileWriter writer) throws IOException {
		int i = 0;
		for (String s : datas) {
			if (s.contains("\"") || s.contains(sepChar) || s.contains("\n") || s.contains("\r")) {
				writer.append('"').append(s).append('"');
			} else {
				writer.append(s);
			}
			if (i++ < datas.length - 1) {
				writer.append(sepChar);
			}
		}
		writer.append('\n');
	}
}
